#!/bin/bash

. n2n.conf

if [ ! "$n2n_supernode_dir" ]; then
	exit 1
fi
if [ ! "$n2n_web" ]; then
	exit 2
fi
#n2n_web=http://gitee.com/breaker0727/n2n-supernode
#n2n_supernode_dir=/storage/n2n-supernode
#tap1_ip=10.1.10.3
#tap2_ip=10.1.10.4
getip=getip
#getwebnode=getsupernode
getwebnode="wget -O - -q $n2n_web/raw/master/supernode.list"
findhole=findhole
testlink=testlink
n2nsyncweb=n2nsyncweb
supernode_localport=12345
supernodelist=$n2n_supernode_dir/supernode.list
app_supernode=supernode
app_edge=edge
udptunnel_port=12346
udpnode_txt=$n2n_supernode_dir/udpnode.txt
tmp_supernode=/run/supernode.list
tmp_udpnode=/run/udpnode.txt
app_udptunnel=udptunnel
#getwebnodeudp=getwebnodeudp
getwebnodeudp="wget -O - -q $n2n_web/raw/master/udpnode.txt"

fgetremoteport()
{
if [ "$1" ]; then
 port=$($findhole $1 $2 )
 if [ "$port" ]; then
 	echo $port
 fi
fi
}

getnode(){
	echo $(cat $tmp_supernode)
}
setnode(){
	echo "setnode="$1
	echo $1 >$tmp_supernode
	echo $1 >$supernodelist
}
initsupernode(){
	node=$(cat $supernodelist)
	echo $node >$tmp_supernode
}
updatesupernode(){
	echo "updatesupernode"
	$n2nsyncweb
}
checksync(){
	remotenode=$($getwebnode)
	localnode=$(getnode)
	if [ "$remotenode" ]; then
		if [ "$remotenode" == "$localnode" ]; then
			echo "ok"
		else
			echo "no"
		fi
	fi
}
update_n2n(){
	echo "getip"
	ip=$($getip)
	echo "ip="$ip
	if [ "$ip" ]; then
		echo "get port"
		port=$(fgetremoteport $ip $supernode_localport)
		if [ "$port" ]; then
			node=$ip":"$port
			setnode $node
		fi
	fi
}
start_n2n(){
	node=$(getnode)
	$app_supernode -p $supernode_localport
	$app_edge -d tap1 -a $tap1_ip -c hstnet -k hstnetkey -l $node
}

stop_n2n(){
	kill -9 $(pidof $app_supernode)
	kill -9 $(pidof $app_edge)
}

restart_n2n(){
	stop_n2n
	update_n2n
	start_n2n
}
restart_edge(){
	kill -9 $(pidof $app_edge)
	node=$($getwebnode)
	echo $node >$tmp_supernode
	$app_edge -d tap2 -a $tap2_ip -c hstnet -k hstnetkey -l $node
}
auto_n2n(){
	initsupernode
	i=0
	while true
	do
		node=$(getnode)
		echo "node"=$node
		resp=$($testlink $node $supernode_localport 2>/dev/null)
		echo "resp"=$resp
		if [ "$resp" = "ok" ]; then
			if [ "$(pidof $app_supernode)" ] && [ "$(pidof $app_edge)" ] ; then
				echo "sleep"
				sleep 30
				let i+=1
				echo "i="$i
				if [ $i -ge 4 ]; then
					let i=0
					resp=$(checksync)
					if [ "$resp" == "no" ]; then
						echo "update ..." 
						updatesupernode
					fi
				fi
			else
				echo "n2n start"				
				start_n2n
			fi
		else
			echo "n2n restart"
			restart_n2n
		fi
	
	done

}
auto_edge(){
	echo "start edge ..."
	restart_edge
	while true
	do
		resp=$(checksync)
		if [ "$resp" == "no" ]; then
			echo "restart edge ..." 
			restart_edge
		fi
		sleep 60
	done
}
keep_link(){
	ip=$($getip)
	localport=$1
	port=$(fgetremoteport $ip $localport)
	node=$ip":"$port
	echo "keep_link:"$node
	while true
	do
		resp=$($testlink $node $localport 2>/dev/null)
		if [ "$resp" = "ok" ]; then
			echo $resp
		else
			echo $resp
		fi
		sleep 30
	done
}
######udptunnel
getudpnode(){
	echo $(cat $tmp_udpnode)
}
setudpnode(){
	echo "setnode="$1
	echo $1 >$tmp_udpnode
	echo $1 >$udpnode_txt
}
initudpnode(){
	node=$(cat $udpnode_txt)
	echo $node >$tmp_udpnode
}
checksyncudp(){
	remotenode=$($getwebnodeudp)
	localnode=$(getudpnode)
	if [ "$remotenode" ]; then
		if [ "$remotenode" == "$localnode" ]; then
			echo "ok"
		else
			echo "no"
		fi
	fi
}
updateudptunnel(){
	echo "updateudptunnel"
	$n2nsyncweb
}
start_udptunnel(){
	echo "start_udptunnel"
	$app_udptunnel -s $udptunnel_port &
}
stop_udptunnel(){
	kill -9 $(pidof $app_udptunnel)
}
update_udptunnel(){
	echo "getip"
	ip=$($getip)
	echo "ip="$ip
	if [ "$ip" ]; then
		echo "get port"
		port=$(fgetremoteport $ip $udptunnel_port)
		if [ "$port" ]; then
			node=$ip":"$port
			setudpnode $node
		fi
	fi
}
restart_udptunnel(){
	stop_udptunnel
	update_udptunnel
	start_udptunnel
}

#auto_link port _cbfun
auto_link(){
	echo "auto_link"
	ip=$($getip)
	localport=$1
	port=$(fgetremoteport $ip $localport)
	node=$ip":"$port
	echo "auto_link:"$node
	$2 $node >/dev/null
	while true
	do
		resp=$($testlink $node $localport 2>/dev/null)
		if [ "$resp" = "ok" ]; then
			echo $resp
		else
			echo $resp
			break
		fi
		sleep 30
	done
}
auto_udptunnel(){
	initudpnode
	i=0
	while true
	do
		node=$(getudpnode)
		echo "node"=$node
		resp=$($testlink $node $udptunnel_port 2>/dev/null)
		echo "resp"=$resp
		if [ "$resp" = "ok" ]; then
			if [ "$(pidof $app_udptunnel)" ]; then
				echo "sleep"
				sleep 30
				let i+=1
				echo "i="$i
				if [ $i -ge 5 ]; then
					let i=0
					resp=$(checksyncudp)
					if [ "$resp" == "no" ]; then
						echo "update ..." 
						updateudptunnel
					fi
				fi
			else
				echo "udptunnel start"				
				start_udptunnel
			fi
		else
			echo "udptunnel restart"
			restart_udptunnel
		fi
	
	done

}

auto_udptunnel2(){
	stop_udptunnel
	while true
	do
		auto_link $udptunnel_port start_udptunnel
		stop_udptunnel
	done
}
case "$1" in
	start)
		start_n2n
	;;
	stop)
		stop_n2n
	;;
	restart)
		restart_n2n
	;;
	update)
		update_n2n
	;;
	auto)
		auto_n2n
	;;
	autoedge)
		auto_edge
	;;
	keeplink)
		keep_link $2
	;;
	autoudp)
		auto_udptunnel
	;;
esac
